<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"
            "http://www.w3.org/TR/REC-html40/loose.dtd">
<HTML>
<HEAD>



<META http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<META name="GENERATOR" content="hevea 1.08">
<LINK rel="stylesheet" type="text/css" href="umsroot.css">
<TITLE>
Events
</TITLE>
</HEAD>
<BODY >
<A HREF="umsroot070.html"><IMG SRC ="contents_motif.gif" ALT="Up"></A>
<A HREF="umsroot072.html"><IMG SRC ="next_motif.gif" ALT="Next"></A>
<HR>

<H2 CLASS="section"><A NAME="htoc172">13.1</A>&nbsp;&nbsp;Events</H2><UL>
<LI><A HREF="umsroot071.html#toc103">Event Identifiers and Event Handling</A>
<LI><A HREF="umsroot071.html#toc104">Raising Events</A>
<LI><A HREF="umsroot071.html#toc105">Events and Waking</A>
<LI><A HREF="umsroot071.html#toc106">Aborting an Execution with Events</A>
</UL>

<A NAME="@default690"></A>
<A NAME="toc103"></A>
<H3 CLASS="subsection"><A NAME="htoc173">13.1.1</A>&nbsp;&nbsp;Event Identifiers and Event Handling</H3>
Events are identified by names (atoms) or by anonymous handles.<BR>
<BR>
When an event is raised, a call to the appropriate handler is inserted
into the resolvent (the sequence of executing goals).
The handler will be executed as soon as possible, which means at the
next synchronous point in execution, which is usually just before the
next regular predicate is invoked. Note that there are a few
built-in predicates that can run for a long time and will not allow
handlers to be executed until they return (e.g. read/1, sort/4).<BR>
<BR>

<H4 CLASS="subsubsection">Creating Named Events</H4>
A named event is created by defining a handler for it using
<A NAME="@default691"></A>
<A HREF="../bips/kernel/event/set_event_handler-2.html"><B>set_event_handler/2</B></A><A NAME="@default692"></A>:
<BLOCKQUOTE CLASS="quote"><PRE CLASS="verbatim">
:- set_event_handler(hello, my_handler/1).
my_handler(Event) :-
    &lt;code to deal with Event&gt;
</PRE></BLOCKQUOTE>
A handler for a named event can have zero or one arguments. When invoked,
the first argument is the event identifier, in this case the atom 'hello'.
It is not possible to pass other information to the handler.<BR>
<BR>
The handler for a defined event can be queried using
<A HREF="../bips/kernel/event/get_event_handler-3.html"><B>get_event_handler/3</B></A><A NAME="@default693"></A>.
<A NAME="@default694"></A><BR>
<BR>

<H4 CLASS="subsubsection">Creating Anonymous Events</H4>
An anonymous event is created with the builtin
<A HREF="../bips/kernel/event/event_create-3.html"><B>event_create/3</B></A><A NAME="@default695"></A>:
<BLOCKQUOTE CLASS="quote"><PRE CLASS="verbatim">
..., event_create(my_other_handler(...), [], Event), ...
</PRE></BLOCKQUOTE>
The builtin takes a handler goal and creates an anonymous event handle Event.
This handle is the only way to identify the event, and therefore must be
passed to any program location that wants to raise the event.
The handler goal can be of any arity and can take arbitrary arguments.
Typically, these arguments would include the Event handle itself and other
ground arguments (variables should not be passed because when the event
is raised, a copy of the handler goal with fresh variables will be executed).<BR>
<BR>
<A NAME="toc104"></A>
<H3 CLASS="subsection"><A NAME="htoc174">13.1.2</A>&nbsp;&nbsp;Raising Events</H3>
Events can be raised in the following different ways:
<UL CLASS="itemize"><LI CLASS="li-itemize">
Explicitly by the ECL<SUP><I>i</I></SUP>PS<SUP><I>e</I></SUP> program itself, using
 <A HREF="../bips/kernel/event/event-1.html"><B>event/1</B></A><A NAME="@default696"></A><A NAME="@default697"></A>.
<LI CLASS="li-itemize">By foreign code (C/C++) using the ec_post_event() function.
<LI CLASS="li-itemize">Via signals/interrupts by setting the interrupt handler to
 <A HREF="../bips/kernel/event/event-1.html"><B>event/1</B></A><A NAME="@default698"></A><A NAME="@default699"></A>.
<LI CLASS="li-itemize">Via I/O streams (e.g. queues can be configured to raise an event
 when they get written into).
<LI CLASS="li-itemize">Via timers, so-called after-events
</UL>

<H4 CLASS="subsubsection">Raising Events Explicitly</H4>
To raise an event from within ECL<SUP><I>i</I></SUP>PS<SUP><I>e</I></SUP> code, call
<A NAME="@default700"></A>
<A HREF="../bips/kernel/event/event-1.html"><B>event/1</B></A><A NAME="@default701"></A> with the event
identifier as its argument. If no handler has been defined, a warning
will be raised:
<BLOCKQUOTE CLASS="quote"><PRE CLASS="verbatim">
?- event(hello).
WARNING: no handler for event in hello
Yes (0.00s cpu)
</PRE></BLOCKQUOTE>
The event can be an anonymous event handle, e.g.
<BLOCKQUOTE CLASS="quote"><PRE CLASS="verbatim">
?- event_create(writeln(handling(E)), [], E), event(E).
handling('EVENT'(16'edbc0b20))
E = 'EVENT'(16'edbc0b20)
Yes (0.00s cpu)
</PRE></BLOCKQUOTE>
Raising events explicitly is mainly useful for test purposes, since
it is almost the same as calling the handler directly.<BR>
<BR>

<H4 CLASS="subsubsection">Raising Events from Foreign Code</H4>
To raise an event from within foreign C/C++ code, call
<BLOCKQUOTE CLASS="quote"><PRE CLASS="verbatim">
ec_post_event(ec_atom(ec_did("hello",0)));
</PRE></BLOCKQUOTE>
This works both when the foreign code is called from ECL<SUP><I>i</I></SUP>PS<SUP><I>e</I></SUP> or when
ECL<SUP><I>i</I></SUP>PS<SUP><I>e</I></SUP> is embedded into a foreign code host program.<BR>
<BR>

<H4 CLASS="subsubsection">Timed Events (after events)</H4>
<A NAME="@default702"></A>
<A NAME="@default703"></A>
<A NAME="@default704"></A>
An event can be triggered after a specified amount
of elapsed time. The event is then handled sychronously by ECL<SUP><I>i</I></SUP>PS<SUP><I>e</I></SUP>.
These events are known as after
events, as they are set up so that the event occurs <I>after</I> a
certain amount of elapsed time.
They are setup by one of the following predicates:<BR>
<BR>

<H5 CLASS="paragraph"><A HREF="../bips/kernel/event/event_after-2.html"><B>event_after(+EventId, +Time)</B></A><A NAME="@default705"></A></H5>
This sets up an event EventId so that the event is raised once after Time seconds
of elapsed time from when the predicate is executed. EventId is an event
identifier and Time is a positive number.<BR>
<BR>

<H5 CLASS="paragraph"><A HREF="../bips/kernel/event/event_after_every-2.html"><B>event_after_every(+EventId, +Time)</B></A><A NAME="@default706"></A></H5> 
This sets up an event EventId so
that the event is raised <I>every</I> Time seconds has elapsed from when
the predicate is executed.<BR>
<BR>

<H5 CLASS="paragraph"><A HREF="../bips/kernel/event/events_after-1.html"><B>events_after(+EventList)</B></A><A NAME="@default707"></A></H5>
This sets up a series of after events specified in EventList, which is list
of events in the form EventId-Time, or EventId-every(Time), specifying a single
event or a repeated event respectively.<BR>
<BR>
The Time parameter is actually the minimum of elapsed time before the
event is raised. Factors constraining the actual time of raising of the
event include the granularity of the system clock, and also that ECL<SUP><I>i</I></SUP>PS<SUP><I>e</I></SUP>
must be in a state where it can <B>synchronously </B> process the event &ndash; 
it needs to be where it can make a procedure call. <BR>
<BR>

Once an after event has been set up, it is pending until it is raised. In
the case of <CODE>event_after_every/2</CODE>, the event will always be pending
because it is rasied repeatedly. A pending event can be cancelled so that
it will not be raised:
<BR>
<BR>

<H5 CLASS="paragraph"><A HREF="../bips/kernel/event/cancel_after_event-2.html"><B>cancel_after_event(+EventId, -Cancelled)</B></A><A NAME="@default708"></A></H5> 
This finds and cancels all pending after events with name EventId and returns
the actually cancelled ones in a list.<BR>
<BR>

<H5 CLASS="paragraph"><A HREF="../bips/kernel/event/current_after_events-1.html"><B>current_after_events(-Events)</B></A><A NAME="@default709"></A></H5> 
This returns a list of all pending after events.<BR>
<BR>
The after event mechanism allows multiple events to make use of the timing
mechanism independently of each other. The same event can be setup
multiple times with multiple calls to <CODE>event_after/2</CODE> and
<CODE>event_after_every/2</CODE>. The <CODE>cancel_after_event/2</CODE> predicate 
will cancel all instances of an event.<BR>
<BR>
By default, the after event feature uses the <TT>real</TT> timer. The
timer can be switched to the <TT>virtual</TT> timer, in which case the
elapsed time measured is user CPU time<SUP><A NAME="text19" HREF="umsroot070.html#note19">1</A></SUP> This
setting is specified by the ECL<SUP><I>i</I></SUP>PS<SUP><I>e</I></SUP> environment flag <TT>after_event_timer</TT> (see get_flag/2, set_flag/2). Note that if the
timer is changed while some after event is still pending, these events
will no longer be processed. The timer should therefore not be changed
once after events are initiated.<BR>
<BR>
Currently, the <TT>virtual</TT> timer is not available on the Windows
platform. In addition, the user should should not make use of these
timers for their own purpose if they plan to use the after event
mechanism.<BR>
<BR>
<A NAME="toc105"></A>
<H3 CLASS="subsection"><A NAME="htoc175">13.1.3</A>&nbsp;&nbsp;Events and Waking</H3>
Using the suspension and event handling mechanisms together, a goal can be
added to the resolvent and executed after a defined elapsed time.
To achieve this, the goal is suspended and attached to a symbolic
trigger, which is triggered by an afer-event handler. The goal behaves
`logically', in that if the execution backtracks pass the point in which
the suspended goal is created, the goal will disappear from the resolvent
as expected and thus not be executed. The event will still be raised, but
there will not be a suspended goal to wake up. Note that if the execution
finishes before the suspended goal is due to be woken up, it will also not
enter the resolvent and is thus not executed.<BR>
<BR>
The following is an example for waking a goal with a timed event.
Once <CODE>monitor(X)</CODE> is called, the current value of X will be
printed every second until the query finishes or is backtracked over:
<BLOCKQUOTE CLASS="quote"><PRE CLASS="verbatim">
:- set_event_handler(monvar, trigger/1).

monitor(Var) :-
     suspend(m(Var), 3, trigger(monvar)),
     event_after_every(monvar, 1).

:- demon m/1.
m(Var) :- writeln(Var).

:- monitor(Var), &lt;do_something&gt;.
</PRE></BLOCKQUOTE>
Note the need to declare
<CODE>m/1</CODE> as a demon: otherwise, once <CODE>m/1</CODE> is woken up once, it will
disappear from the resolvent and the next <CODE>monvar</CODE> event will not have
a suspended <CODE>m/1</CODE> to wake up.
Note also that it is necessary to connect the event machanism to
the waking mechanism by setting the event handler to <A HREF="../bips/kernel/suspensions/trigger-1.html"><B>trigger/1</B></A><A NAME="@default710"></A>.<BR>
<BR>
<A NAME="toc106"></A>
<H3 CLASS="subsection"><A NAME="htoc176">13.1.4</A>&nbsp;&nbsp;Aborting an Execution with Events</H3>
Typically, event handlers would perform some action and then succeed,
letting the interrupted exectuion continue unharmed. Event handlers for
asynchronous events should never fail, because the failure will be inserted
in a random place in resolvent, and the effect will be unpredictable.
It is however sometimes useful to allow an asynchronous event to abort
an execution (via 
<A HREF="../bips/kernel/control/exit_block-1.html"><B>exit_block/1</B></A><A NAME="@default711"></A>), e.g.
to implement timeouts<SUP><A NAME="text20" HREF="umsroot070.html#note20">2</A></SUP>.<BR>
<BR>
When dealing with events that occur asynchronously (in particular after-events),
and event handlers that cause the execution to abort, it is often a problem
that event handlers may be interrupted or preempted by other event handlers.
This can be avoided by use of the event-defer mechanism. Events can be
declared with the defer-property, which means that all further event handling
is temporarily suppressed as soon as the handling of this event begins.
In this case, the event handler is responsible for reenabling event handling
explicitly before returning by calling
<A HREF="../bips/kernel/event/events_nodefer-0.html"><B>events_nodefer/0</B></A><A NAME="@default713"></A>.
For instance:
<BLOCKQUOTE CLASS="quote"><PRE CLASS="verbatim">
:- set_event_handler(my_event, defers(my_handler/0)).
my_after_handler :-       % event handling is deferred at this point
        &lt;deal with event&gt;,
        events_nodefer.   % allow other events to be handled again
</PRE></BLOCKQUOTE>
In the presence of other event handlers which can cause aborts, this will
protect the handler code from being preempted.<BR>
<BR>
<HR>
<A HREF="umsroot070.html"><IMG SRC ="contents_motif.gif" ALT="Up"></A>
<A HREF="umsroot072.html"><IMG SRC ="next_motif.gif" ALT="Next"></A>
</BODY>
</HTML>
